#pragma once
#include <crtdbg.h>
#include <stdio.h>
# if defined(__GNUC__)
#define LIKELY(exp)   __builtin_expect(!!(exp), 1)
#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
#define FORCE_INLINE  __attribute__((always_inline))
#elif defined(_MSC_VER)
#define LIKELY(exp)   (exp)
#define UNLIKELY(exp) (exp)
#define FORCE_INLINE
#endif

#define ASSERT(exp)             \
    do {                            \
        if (LIKELY(exp)) break; \
        __DO_ASSERT(exp);       \
    } while (0)

#define ASSERT_RETURN_VALUE(exp, val) \
    do {                                  \
        if (LIKELY(exp)) break;       \
        __DO_ASSERT(exp);             \
        return (val);                     \
    } while (0)

#define ASSERT_RETURN_VOID(exp) \
    do {                            \
        if (LIKELY(exp)) break; \
        __DO_ASSERT(exp);       \
        return;                     \
    } while (0)

#define ASSERT_RETURN_NULL(exp)  ASSERT_RETURN_VALUE(exp, nullptr)
#define ASSERT_RETURN_TRUE(exp)  ASSERT_RETURN_VALUE(exp, true)
#define ASSERT_RETURN_FALSE(exp) ASSERT_RETURN_VALUE(exp, false)

#define __DO_ASSERT(exp)                 \
    printf("assertion failure: %s", #exp); _ASSERT(exp);
